﻿using UnityEngine;

namespace GameToolkit.BehaviourTree
{
    [System.Serializable]
    [CompositeTitle("子行为树", Description = "Sub Behaviour Tree")]
    [CompositeCategory]
    [CompositeIcon("2b6bdb18a30c4e94c9aa071f06ea25c9")]
    public class SubBehaviourTree : ExecutableComposite
    {
        [SerializeField]
        BehaviourTreeAsset m_BehaviourTree;

        [SerializeField]
        string m_BehaviourFromBlackboard;

#if UNITY_EDITOR
        public override string GetDescription()
        {
            if(m_BehaviourTree != null)
            {
                var path = UnityEditor.AssetDatabase.GetAssetPath(m_BehaviourTree);
                return string.IsNullOrEmpty(path) ? m_BehaviourTree.name : path;
            }
            else
            {
                return null;
            }
        }
#endif

        public override BehaviourTreeObject Create()
        {
            return new Impl();
        }


        class Impl : ActionNode, IBehaviourTreeBinder
        {
            BehaviourTreePlayer mPlayer;
            SubBehaviourTree mCfg;

            protected override void OnDestroy(BehaviourTreePlayer player)
            {
            }

            public BehaviourTreeAsset behaviourTreeAsset => mCfg?.m_BehaviourTree;

            public BehaviourTreePlayer GetPlayerForAsset(BehaviourTreeAsset asset)
            {
                return mPlayer == null ? null : mPlayer.FindPlayerForAsset(asset);
            }

            protected override void OnCreate(BehaviourTreePlayer player)
            {
                mCfg = composite as SubBehaviourTree;
#if UNITY_EDITOR
                mPlayer = player.CreateSubTreePlayer(this, guid);
#else
                mPlayer = player.CreateSubTreePlayer(this);
#endif
            }

            protected override bool IsExecutable(BehaviourTreePlayer player)
            {
                return mCfg.m_BehaviourTree != null;
            }

            protected override void OnStart(BehaviourTreePlayer player)
            {
                BehaviourTreeAsset asset;
                if (string.IsNullOrEmpty(mCfg.m_BehaviourFromBlackboard) || !player.Executable.GetBlackboard(mCfg.m_BehaviourFromBlackboard, out asset) || asset == null)
                    asset = mCfg.m_BehaviourTree;
                mPlayer.SetBehaviourTree(asset);
            }

            protected override void OnStop(BehaviourTreePlayer player)
            {
                mPlayer.MainLooper?.Interrupt(false, State == NodeState.Success);
            }

            protected override NodeState OnUpdate(BehaviourTreePlayer player)
            {
                mPlayer.UpdateBehaviour(player.DeltaTime);
                return mPlayer.State;
            }
        }
    }
}
